#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    int port = 8000;
    //  int fd = open("123123.txt");
    // 1.创建一个 socket，并将其设置为监听状态。CPU只能读内存，磁盘和网络都是外设
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    // 需要一个网络地址，用来给 client 连接， 比如 80
    server_addr.sin_family = AF_INET; // ip协议
    server_addr.sin_port = htons(port);  // 端口
    server_addr.sin_addr.s_addr = INADDR_ANY; // 网卡
    
    // 一般 server 都要用，不然会出现端口占用的问题 ，SO_REUSEADDR
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    
    // 2.使用bind()函数将socket绑定到本地IP地址和端口上。
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }
    
    // 3.使用listen()函数开始监听端口，等待客户端的连接请求。  服务器 开启一个 queue 存放最多n个 client 的连接信息
    if (listen(server_fd, 5) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    printf("Server listening on port %d.\n", port);

    // 4.在一个无限循环中接受客户端的连接请求，并对每个连接请求进行处理。
    while (1) {
    
        // 5.在处理请求时，使用accept()函数接受客户端连接，并读取客户端发送的数据。
        client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);
        printf("Client accept. %d \n", client_fd);
        if (client_fd == -1) {
            perror("accept");
            exit(EXIT_FAILURE);
        }

        char buffer[1024] = {0}; // 1024 个字节
        // 读出客户端发来的数据
        ssize_t bytes_received = read(client_fd, buffer, sizeof(buffer));

        printf("Received request: %s\n", buffer);

        // 6.回显客户端发送的数据，并发送响应数据。
        ssize_t bytes_sent = write(client_fd, buffer, sizeof(buffer));
        if (bytes_sent < 0) {
            perror("write");
            close(client_fd);
            continue;
        } else {
            printf("Response sent: %zd bytes\n", bytes_sent);
        }

        // 7.关闭连接。
        close(client_fd);
    }

    close(server_fd);
    return 0;
}
